package com.example.usb.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.baidu.aip.util.Base64Util;
import com.example.usb.MyApplication;
import com.example.usb.ai.AiLibManager;
import com.example.usb.ai.AiV3Bean;
import com.example.usb.ai.FaceRegisterBean;
import com.example.usb.ai.FaceStandardUtil;
import com.example.usb.ai.SearchFaceBean;
import com.lib.uvccamera.bean.FaceBean;
import com.lib.uvccamera.bean.MessageEvent;
import com.example.usb.dao.DbConstant;
import com.example.usb.dao.entity.FaceInfoBean;
import com.example.usb.dao.entity.PhotoPicBean;
import com.example.usb.dao.util.FaceDaoUtil;
import com.example.usb.dao.util.PhotoPicDaoUtil;
import com.lib.uvccamera.utils.AppUtil;
import com.lib.uvccamera.utils.DebugLog;
import com.lib.uvccamera.utils.FileUtils;

import org.greenrobot.eventbus.EventBus;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.lib.uvccamera.utils.Aiconstant.HAS_FACE_ERROR_MESSAGE;
import static com.lib.uvccamera.utils.Aiconstant.HAS_FACE_MESSAGE;
import static com.lib.uvccamera.utils.Aiconstant.HAS_FACE_TWO_MESSAGE;
import static com.lib.uvccamera.utils.Aiconstant.NO_FACE_MESSAGE;

/**
 * 百度智能人脸识别
 * Created by Administrator on 2018/4/18.
 */

public class AiV3Util {
    private static SimpleDateFormat sdf = new SimpleDateFormat("HHmmssSSS", Locale.CHINA);
    private static final List<String> PIC_QUEUE = new ArrayList<>();
    private static AiV3Util mAIUtil = null;
    private int code;
    private List<FaceBean> faceBeans;

    private AiV3Util() {

    }

    /**
     * 单例模式
     *
     * @return 构造方法
     */
    public static synchronized AiV3Util getInstance() {
        if (mAIUtil == null) {
            synchronized (AiV3Util.class) {
                if (mAIUtil == null) {
                    mAIUtil = new AiV3Util();
                }
            }

        }
        return mAIUtil;
    }


    /**
     * 比较人脸
     *
     * @param md5          标识
     * @param compressPath 图片压缩后的路径
     * @param hscPicBean   一张MD5对应的bean类
     * @throws Exception
     */
    public void getManage(String md5, String compressPath, PhotoPicBean hscPicBean) throws Exception {
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage start-------------------------------------------------------------- ");
        //图片
        Bitmap userBitmap = BitmapFactory.decodeFile(compressPath);//filePath
        byte[] userByte = FileUtils.readFileByBytes(compressPath);
        //人脸检测
        AiV3Bean aiBean = AiLibManager.getInstance().detectFace(Base64Util.encode(userByte));
        AiV3Bean.Result resultData = aiBean.getResult();
        //返回多张人脸
        if (resultData != null && resultData.getFaceNum() > 0) {
            DebugLog.d(DebugLog.LOGHsc + "-----检测人脸几个---- " + resultData.getFaceNum());
            //图片中有人脸
            int resultNum = resultData.getFaceNum();
            //更新图片人脸数目
            PhotoPicDaoUtil.getInstance().updataPicFaceNum(hscPicBean, resultNum, DbConstant.PIC_HAS_DETECTION);
            //图片中有2个人脸
            if (resultNum > 1) {
                List<FaceBean> faceBeans = new ArrayList<FaceBean>();
                //获取所有的人脸
                List<AiV3Bean.FaceList> faceListList = aiBean.getResult().getFaceList();
                for(int i = 0; i < faceListList.size(); i++){
                    FaceBean faceBean;
                    AiV3Bean.FaceList faceInfo = aiBean.getResult().getFaceList().get(i);
                    //获取裁剪的人头
                    Bitmap headBitmap = ImageUtils.getRotateImgae(faceInfo, userBitmap);
                    byte[] bitmapByte = ImageUtils.bitmap2StrByte(headBitmap);
//                  去人脸库对比,用于计算指定组内用户，与上传图像中人脸的相似度。识别前提为您已经创建了一个人脸库
                    SearchFaceBean searchFaceBean = AiLibManager.getInstance().SearchFace(Base64Util.encode(bitmapByte));
                    //每张人脸拿去搜索

                    faceBean = indentify_more(md5, searchFaceBean, faceInfo, compressPath, headBitmap, hscPicBean, bitmapByte);
                    faceBeans.add(faceBean);
                }
                sendMsgList(HAS_FACE_TWO_MESSAGE, faceBeans);
            } else {
                //只有一个人脸的，获取脸部数据
                AiV3Bean.FaceList faceList = aiBean.getResult().getFaceList().get(0);
                //获取裁剪的人头
                Bitmap headBitmap = ImageUtils.getRotateImgae(faceList, userBitmap);
                byte[] bitmapByte = ImageUtils.bitmap2StrByte(headBitmap);
//                去人脸库对比,用于计算指定组内用户，与上传图像中人脸的相似度。识别前提为您已经创建了一个人脸库
                SearchFaceBean searchFaceBean = AiLibManager.getInstance().SearchFace(Base64Util.encode(bitmapByte));
                //每张人脸拿去搜索
                indentify(md5, searchFaceBean, faceList, compressPath, headBitmap, hscPicBean, bitmapByte);
            }


        } else {
            //图片中没有人脸更新人脸为1及人脸路径数据到数据库
            DebugLog.d(DebugLog.LOGHsc + " ---没有人脸的图片-----2222 ");
//            SQLiteUtils.getInstance(MyApplication.getContext()).updateFigureData(md5, "1", "-1", "", compressPath, hscPicBean, 0.00d);
            PhotoPicDaoUtil.getInstance().updataPicFaceNum(hscPicBean, 0, DbConstant.PIC_HAS_DETECTION);
            List<FaceBean> faceBeans = new ArrayList<FaceBean>();
            FaceBean faceBean = new FaceBean(compressPath,"","",0d);
            faceBeans.add(faceBean);
//            sendMsg(NO_FACE_MESSAGE, compressPath, "", "", 0d);
            sendMsgList(NO_FACE_MESSAGE,faceBeans);

        }
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage end-------------------------------------------------------------- ");
    }

    /**
     * 处理搜索到的人脸结果
     *
     * @param md5            图片唯一标识
     * @param searchFaceBean 搜到的人脸结果
     * @param faceList       需要识别人脸属性
     * @param compressPath   压缩路径
     * @param headBitmap     图片
     * @param hscPicBean     图片表
     * @param bitmapByte     图片流
     */
    private void indentify(String md5, SearchFaceBean searchFaceBean, AiV3Bean.FaceList faceList, String compressPath, Bitmap headBitmap, PhotoPicBean hscPicBean, byte[] bitmapByte) {
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage indentify-start-------------------------------------------------------------- ");
        double faceScore = 0.00d;
        //人脸唯一标志
        String finger = "";
        //储存人头
        String headPath = FileUtils.saveHeadPic(bitmapByte, FileUtils.ROOT_PATH + AppUtil.getPackageName(MyApplication.getContext()) + FileUtils.HEAD_PATH);
        if (searchFaceBean != null && searchFaceBean.getResult() != null) {
            //Ai库里搜索到的结果不为空
            SearchFaceBean.Result result = searchFaceBean.getResult();
            List<SearchFaceBean.Result.UserBean> userList = result.getUser_list();
            if (userList != null && userList.size() > 0) {
                //返回的人脸搜索,获取相似度最大值
                SearchFaceBean.Result.UserBean userBean = userList.get(0);
                //返回匹配的人脸库的信息，带userId
                finger = userBean.getUserId();
                //返回组信息
                String groupId = userBean.getGroupId();
                //添加人脸uid
                double maxScore = userBean.getScore();
                DebugLog.d(DebugLog.LOGHsc + " 人头路径 -=-headPath " + headPath + " 搜索到的 size " + userList.size() + " finger " + finger + " maxScore " + maxScore + " groupId " + groupId);
                //新人脸打分
                faceScore = FaceStandardUtil.getFaceScore(faceList);
//                DebugLog.d(DebugLog.LOGHsc + "lius 人脸打分 -=-faceScore： " + faceScore);
                //比较
                if (maxScore >= 55) {
                    //有相似，讲截取的人头新的分数与AI库和本地数据库的人头做比较，如果分数高，更新本地和AI库
                    FaceInfoBean localBean = FaceDaoUtil.getInstance().getFaceBeanByFinger(finger);
                    //此时AI库有，但本地数据库没有,更新本地数据库的分数
                    if (localBean == null) {
                        DebugLog.d(DebugLog.LOGHsc + " Ai库有人脸，本地数据库没有=---- 人脸kun符合规则 新faceScore " + faceScore);
                        FaceDaoUtil.getInstance().insertFaceBean(faceList, md5, faceScore, finger, headPath, headPath, compressPath);
                        List<FaceBean> faceBeans = new ArrayList<FaceBean>();
                        FaceBean faceBean = new FaceBean(compressPath,finger,headPath,maxScore);
                        faceBeans.add(faceBean);
                        sendMsgList(HAS_FACE_MESSAGE,faceBeans);
//                        sendMsg(HAS_FACE_MESSAGE, compressPath, headPath, finger, 0d);
                        return;
                    }
                    //TODO：有相似的脸
                    List<FaceBean> faceBeans = new ArrayList<FaceBean>();
                    FaceBean faceBean = new FaceBean(compressPath,finger,headPath,maxScore);
                    faceBeans.add(faceBean);
                    sendMsgList(HAS_FACE_MESSAGE,faceBeans);
//                    sendMsg(HAS_FACE_MESSAGE, compressPath, headPath, finger, maxScore);
//
                } else {
                    //Ai库搜索到人脸但不相似，不代表同一人，注册人脸
                    regiestFace(md5, faceList, compressPath, bitmapByte, headPath);
                }
            }
        } else {
            //AI库没有搜索到人脸-注册
            regiestFace(md5, faceList, compressPath, bitmapByte, headPath);
        }
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage indentify-end-------------------------------------------------------------- ");

    }

    /**
     * 多人脸处理
     *
     * @param md5            图片唯一标识
     * @param searchFaceBean 搜到的人脸结果
     * @param faceList       需要识别人脸属性
     * @param compressPath   压缩路径
     * @param headBitmap     图片
     * @param hscPicBean     图片表
     * @param bitmapByte     图片流
     */
    private FaceBean indentify_more(String md5, SearchFaceBean searchFaceBean, AiV3Bean.FaceList faceList, String compressPath, Bitmap headBitmap, PhotoPicBean hscPicBean, byte[] bitmapByte) {
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage indentify-start-------------------------------------------------------------- ");
        double faceScore = 0.00d;
        FaceBean faceBean = null;
        //人脸唯一标志
        String finger = "";
        //储存人头
        String headPath = FileUtils.saveHeadPic(bitmapByte, FileUtils.ROOT_PATH + AppUtil.getPackageName(MyApplication.getContext()) + FileUtils.HEAD_PATH);
        if (searchFaceBean != null && searchFaceBean.getResult() != null) {
            //Ai库里搜索到的结果不为空
            SearchFaceBean.Result result = searchFaceBean.getResult();
            List<SearchFaceBean.Result.UserBean> userList = result.getUser_list();
            if (userList != null && userList.size() > 0) {
                //返回的人脸搜索,获取相似度最大值
                SearchFaceBean.Result.UserBean userBean = userList.get(0);
                //返回匹配的人脸库的信息，带userId
                finger = userBean.getUserId();
                //返回组信息
                String groupId = userBean.getGroupId();
                //添加人脸uid
                double maxScore = userBean.getScore();
                DebugLog.d(DebugLog.LOGHsc + " 人头路径 -=-headPath " + headPath + " 搜索到的 size " + userList.size() + " finger " + finger + " maxScore " + maxScore + " groupId " + groupId);
                //新人脸打分
                faceScore = FaceStandardUtil.getFaceScore(faceList);
//                DebugLog.d(DebugLog.LOGHsc + "lius 人脸打分 -=-faceScore： " + faceScore);
                //比较
                if (maxScore >= 55) {
                    //有相似，讲截取的人头新的分数与AI库和本地数据库的人头做比较，如果分数高，更新本地和AI库
                    FaceInfoBean localBean = FaceDaoUtil.getInstance().getFaceBeanByFinger(finger);
                    //此时AI库有，但本地数据库没有,更新本地数据库的分数
                    if (localBean == null) {
                        DebugLog.d(DebugLog.LOGHsc + " Ai库有人脸，本地数据库没有=---- 人脸kun符合规则 新faceScore " + faceScore);
                        FaceDaoUtil.getInstance().insertFaceBean(faceList, md5, faceScore, finger, headPath, headPath, compressPath);
                        faceBean = new FaceBean(compressPath, finger,headPath, maxScore);
                        return faceBean;
                    }
                    //TODO：有相似的脸
                    faceBean = new FaceBean(compressPath,finger, headPath, maxScore);
//                    sendMsg(HAS_FACE_MESSAGE, compressPath, headPath, finger, maxScore);
//
                } else {
                    //Ai库搜索到人脸但不相似，不代表同一人，注册人脸
                    regiestFace(md5, faceList, compressPath, bitmapByte, headPath);
                }
            }
        } else {
            //AI库没有搜索到人脸-注册
            regiestFace(md5, faceList, compressPath, bitmapByte, headPath);
        }
        DebugLog.d(DebugLog.LOGHsc + " -------------------------------------getManage indentify-end-------------------------------------------------------------- ");

        return faceBean;
    }





    /**
     * 针对AI库搜索不到人脸或者有人脸但不相似在去注册
     *
     * @param md5          图片md5
     * @param faceList     人脸的属性数据
     * @param compressPath 图片压缩路径
     * @param bitmapByte   人头二进制流
     * @param headPath     人头路径
     */
    private void regiestFace(String md5, AiV3Bean.FaceList faceList, String compressPath, byte[] bitmapByte, String headPath) {

//        boolean registerFace = FaceStandardUtil.isRegisterFace(faceList, headBitmap);
        //如果判断是人脸，注册
        double faceScore = FaceStandardUtil.getFaceScore(faceList);
        String finger = sdf.format(new Date());
        DebugLog.d(DebugLog.LOGHsc + " AI库没有搜索到---finger- " + finger);
        //注册人脸
        FaceRegisterBean faceRegisterBean = AiLibManager.getInstance().registerFacebyBase64(Base64Util.encode(bitmapByte), finger);
        if (faceRegisterBean.getError_code().equals("0")) {
            DebugLog.d(DebugLog.LOGHsc + " 不是一样人脸kun 注册成功--------11111111- faceScore " + faceScore + " figure " + faceRegisterBean.getFaceToken());
            FaceDaoUtil.getInstance().insertFaceBean(faceList, md5, faceScore, finger, headPath, headPath, compressPath);

            List<FaceBean> faceBeans = new ArrayList<FaceBean>();
            FaceBean faceBean = new FaceBean(compressPath,finger,headPath,faceScore);
            faceBeans.add(faceBean);
            sendMsgList(HAS_FACE_MESSAGE,faceBeans);
//
//            sendMsg(HAS_FACE_MESSAGE, compressPath, headPath, finger, 0d);
        } else {
            DebugLog.d(DebugLog.LOGHsc + " 不是一样人脸 注册失败--------1111111-faceScore ");
            String errorString = ErrorUtil.getErrorString(faceRegisterBean.getError_code());

            List<FaceBean> faceBeans = new ArrayList<FaceBean>();
            FaceBean faceBean = new FaceBean(compressPath,errorString,headPath,faceScore);
            faceBeans.add(faceBean);
            sendMsgList(HAS_FACE_ERROR_MESSAGE,faceBeans);
//            sendMsg(HAS_FACE_ERROR_MESSAGE, compressPath, headPath, errorString, 0d);
        }

    }

//
//    /**
//     * 发送人头信息显示到主界面
//     *
//     * @param code         发送码
//     * @param compressPath 拍照的图片
//     * @param headPath     人头路径
//     * @param finger       人脸标识
//     * @param matchScore   匹配分数
//     */
//    private void sendMsg(int code, String compressPath, String headPath, String finger, double matchScore) {
//        FaceBean faceBean = new FaceBean(compressPath, finger, headPath, matchScore);
//        EventBus.getDefault().post(new MessageEvent(code, faceBean));
//    }

    /**
     * 发送2个人头信息显示到主界面
     *
     * @param requestCode 发送码 HAS_FACE_TWO_MESSAGE
     * @param beans       人脸bean
     */
    private void sendMsgList(int requestCode, List<FaceBean> beans) {

        EventBus.getDefault().post(new MessageEvent(requestCode, beans));
    }


}
